
#include "app_nfc.h"



// #include "system_clock.h"
HardwareTimer Timer0;
// STM32Timer ITimer0(TIM22);
#if defined(TEST)
#define TIMER0_INTERVAL_MS 2000 // 10000//200//500
#else
#define TIMER0_INTERVAL_MS 200 // 10000//200//500
#endif
// // #define TIMER0_DURATION_MS        5000
// HardwareTimer Timer0(TIM22);

extern uint8_t *image_buffer_black;

static uint8_t *nfcBuffer;

// extern uint8_t *image_buffer;
// extern uint8_t *image_buffer_temp;
uint8_t cnt = 0;
uint16_t mblength;
ST25DV_MB_CTRL_DYN_STATUS mbctrldynstatus;
ST25DV_EN_STATUS MB_mode;
ST25DV_PASSWD passwd;
ST25DV_I2CSSO_STATUS i2csso;
volatile uint8_t GPOActivated = 0;
volatile uint8_t NFCIsBusy = 0;
volatile uint8_t TimerInterruptFlag = 0;

volatile uint8_t display_flag = 0;

volatile uint8_t nfc_data_flag = 0;
int nfc_data_times = 0;

int bufferIndex = 0;
int epd_adc_times = 0;

void BSP_GPO_Callback(void);
void MX_NFC4_MAILBOX_Init(void);

void Timer0Handler();

void MX_NFC4_MAILBOX_Process(void);



void MX_NFC_Init(void)
{

#if defined(TIM1)
    TIM_TypeDef *Instance = TIM1;
#else
    TIM_TypeDef *Instance = TIM2;
#endif
    Timer0.setup(Instance);
    Timer0.setOverflow(TIMER0_INTERVAL_MS * 1000, MICROSEC_FORMAT); //
    Timer0.attachInterrupt(Timer0Handler);                          //
    Timer0.resume();
    // printf("00000\n");
#ifndef VERSION2
    nfcBuffer = (uint8_t *)malloc(5000);
#endif

    MX_NFC4_MAILBOX_Init();
    // memset(nfcBuffer, 0xFF, 5000);
    bufferIndex = 0;
 
}

void MX_NFC_Process(void)
{
    MX_NFC4_MAILBOX_Process();
}

void MX_NFC4_MAILBOX_Init(void)
{
    /* Init ST25DV driver */
    while (NFC04A1_NFCTAG_Init(NFC04A1_NFCTAG_INSTANCE) != NFCTAG_OK)
        ;

    /* You need to present password to change static configuration */
    NFC04A1_NFCTAG_ReadI2CSecuritySession_Dyn(NFC04A1_NFCTAG_INSTANCE, &i2csso);
    if (i2csso == ST25DV_SESSION_CLOSED)
    {
        /* if I2C session is closed, present password to open session */
        passwd.MsbPasswd = 0;
        passwd.LsbPasswd = 0;
        NFC04A1_NFCTAG_PresentI2CPassword(NFC04A1_NFCTAG_INSTANCE, passwd);
    }

    /* Energy harvesting activated after Power On Reset */
    NFC04A1_NFCTAG_WriteEHMode(NFC04A1_NFCTAG_INSTANCE, ST25DV_EH_ACTIVE_AFTER_BOOT);
    NFC04A1_NFCTAG_SetEHENMode_Dyn(NFC04A1_NFCTAG_INSTANCE);

    /* If not activated, activate Mailbox, as long as MB is ON EEPROM is not available */
    NFC04A1_NFCTAG_ReadMBMode(NFC04A1_NFCTAG_INSTANCE, &MB_mode);
    if (MB_mode == ST25DV_DISABLE)
    {
        /* You need to present password before changing static configuration */
        NFC04A1_NFCTAG_ReadI2CSecuritySession_Dyn(NFC04A1_NFCTAG_INSTANCE, &i2csso);
        if (i2csso == ST25DV_SESSION_CLOSED)
        {
            /* if I2C session is closed, present password to open session */
            passwd.MsbPasswd = 0; /* Default value for password */
            passwd.LsbPasswd = 0; /* change it if password has been modified */
            NFC04A1_NFCTAG_PresentI2CPassword(NFC04A1_NFCTAG_INSTANCE, passwd);
        }
        NFC04A1_NFCTAG_WriteMBMode(NFC04A1_NFCTAG_INSTANCE, ST25DV_ENABLE);

        /* Close session as dynamic register doesn't need open session for modification */
        passwd.MsbPasswd = 123;
        passwd.LsbPasswd = 123;
        NFC04A1_NFCTAG_PresentI2CPassword(NFC04A1_NFCTAG_INSTANCE, passwd);
    }

    /* Enable Mailbox in dynamique register */
    NFC04A1_NFCTAG_SetMBEN_Dyn(NFC04A1_NFCTAG_INSTANCE);
    // printf("\n\r\n\rMailbox is activated");
    printf("Mailbox is activated\n");

    /* Set EXTI settings for GPO Interrupt */

    pinMode(GPO_PIN, INPUT);
    attachInterrupt(GPO_PIN, BSP_GPO_Callback, FALLING); // 创建中断


    /* Present configuration password */
    passwd.MsbPasswd = 0; /* Default value for password */
    passwd.LsbPasswd = 0; /* change it if password has been modified */
    NFC04A1_NFCTAG_PresentI2CPassword(NFC04A1_NFCTAG_INSTANCE, passwd);
    /* Set GPO Configuration */
    NFC04A1_NFCTAG_ConfigIT(NFC04A1_NFCTAG_INSTANCE,
                            ST25DV_GPO_ENABLE_MASK | ST25DV_GPO_RFGETMSG_MASK | ST25DV_GPO_RFPUTMSG_MASK);
}

/**
 * @brief  Process of the MAILBOX application
 * @retval None
 */

void MX_NFC4_MAILBOX_Process(void)
{

    if (GPOActivated == 1)
    {
        NFCIsBusy=1;
        while (1)
        {

            if (GPOActivated==0)
            {
                break;
            }
            /* Check if Mailbox is available */
            NFC04A1_NFCTAG_ReadMBCtrl_Dyn(NFC04A1_NFCTAG_INSTANCE, &mbctrldynstatus);
            // printf("GPO is acti

            if (mbctrldynstatus.RfPutMsg == 1)
            {
                /* Read length of message */
                NFC04A1_NFCTAG_ReadMBLength_Dyn(NFC04A1_NFCTAG_INSTANCE, (uint8_t *)&mblength);
                mblength += 1;
                printf("num:%d\n", mblength);
                // #define DEBUG 1
                // #if DEBUG
                /* Read mailbox status */
                // NFC04A1_NFCTAG_ReadMBCtrl_Dyn(NFC04A1_NFCTAG_INSTANCE, &mbctrldynstatus);
                // printf("Ctrl MB status register value:\n");
                // printf("Host(i2c) Missed Message  = %d\n", mbctrldynstatus.HostMissMsg);
                // printf("RF(reader) Missed Message = %d\n", mbctrldynstatus.RFMissMsg);
                // printf("Host(i2c) Put Message     = %d\n", mbctrldynstatus.HostPutMsg);
                // printf("RF(reader) Put Message    = %d\n", mbctrldynstatus.RfPutMsg);
                // printf("Mailbox Enable            = %d\n\n", mbctrldynstatus.MbEnable);
                // // #endif

#ifdef VERSION2
                if (mblength > 0) // frame header
                {
                    uint8_t nfc_data[300];
                    NFC04A1_NFCTAG_ReadMailboxData(NFC04A1_NFCTAG_INSTANCE, nfc_data, 0, mblength);
                    uint8_t cmdtype = 0;
                    EpdCmdWrite(nfc_data, mblength);
                    nfc_data_flag = display_flag ? 0 : 1;
                    epd_adc_times = display_flag ? 0 : 1;
                    ;
                    // PRINT_DEBUG("display_flag:%d", display_flag);
                    nfc_data_times = 0;
                }
#else
                if (mblength == 3) // frame header
                {
                    bufferIndex = 0;
                }

                else if (mblength < 300) // test!!!
                {
                    uint8_t temp[300];
                    NFC04A1_NFCTAG_ReadMailboxData(NFC04A1_NFCTAG_INSTANCE, temp, 0, mblength);
                    for (int i = 0; i < mblength; i++)
                    {
                        PRINT_RAW("%02x ", temp[i]);
                    }
                    PRINT_RAW("\n");
                }
                else if (mblength == 200) // picture data
                {
                    nfc_data_flag = 1;
                    nfc_data_times = 0;
                    //  Timer0.pause();

                    //    Timer0.setCount(0,MICROSEC_FORMAT);
                    //    Timer0.refresh();
                    // ITimer0.restartTimer();
                    // digitalWrite(LED0, HIGH);
                    // digitalToggle(LED0);

                    /* Read all data in Mailbox */
                    // uint8_t temp[500];
                    // NFC04A1_NFCTAG_ReadMailboxData(NFC04A1_NFCTAG_INSTANCE, temp, 0, 200);

                    NFC04A1_NFCTAG_ReadMailboxData(NFC04A1_NFCTAG_INSTANCE, nfcBuffer + bufferIndex, 0, 200);
                    if (bufferIndex < 300)
                    {
                        for (int i = 0; i < 200; i++)
                        {
                            PRINT_RAW("%02x ", nfcBuffer[bufferIndex + i]);
                        }
                        PRINT_RAW("\n");
                    }
                    // for (int i = 0; i < 200; i++)
                    // {
                    //     nfcBuffer[bufferIndex + i] = temp[i];
                    // }
                    // PRINT_RAW("\n");
                    bufferIndex += 200;
                    // delay(100);
                    // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
                    // digitalWrite(LED0, LOW);
                    digitalToggle(LED0);
                    printf("buffer total size:%d\n\n", bufferIndex);
                }

                if (bufferIndex == 5000)
                {
                    nfc_data_flag = 0;
                    nfc_data_times = 0;
                    // ITimer0.stopTimer();
                    // Timer0.pause();
                    bufferIndex = 0;
                    display_flag = 1;
                    epd_adc_times = 0;
                    digitalWrite(LED0, LOW);
                    HAL_Delay(30);
                }
#endif
            }

            // SystemClock_MSI2_Config();
            GPOActivated -=1;
        }
            NFCIsBusy=0;
    }

    while (display_flag > 0)
    {
        // SystemClock_HSI16_Config();
        Timer0.pause();

        uint32_t EPD_Vol = 2 * ADC_READ_Voltage(EPD_ADC);
        PRINT_INFO("EPD VOL : %dmv\n", EPD_Vol);

        // Timer0.pause();

        if (EPD_Vol > EPD_MIN_VOL)
        {
            // digitalWrite(LED0, HIGH);
            // if (EPD_Vol > EPD_VOL_TIMER)
            // {
            //     digitalWrite(LED1, HIGH);
            // }
            digitalWrite(LED0, LOW);
            digitalWrite(LED1, LOW);
#if EPD_COLOR == 2
            if (display_flag == 1)
            {


#ifdef VERSION2
                // digitalWrite(LED0, LOW);
                PRINT_DEBUG("time:%d\n", millis());
                // eink_display();
                eink_TurnOnDisplay(EPD_DISPLAY_FULL);
                PRINT_DEBUG("time:%d\n", millis());
                digitalWrite(LED0, HIGH);

#else
                EPD_1IN54_Display(nfcBuffer);


                HAL_Delay(30);
#endif
            }
#ifdef VERSION3
            else if (display_flag == 2)
            {


                PRINT_DEBUG("time:%d\n", millis());
                // EPD_1IN54_Grey_Clear();
                eink_grey_data_inti();
                eink_grey_display(0);
                // eink_clear();
                digitalWrite(LED0, HIGH);
                // HAL_Delay(100);
                // eink_grey_inti();

                PRINT_DEBUG("time:%d\n", millis());
                // if (greyscale == 4)
                //     HAL_Delay(100);
                // else if (greyscale == 16)
                //     HAL_Delay(100);
                for (int i = 1; i < greyscale; i++)
                {
                    PRINT_DEBUG("time:%d\n", millis());
                    bool grey_display_flag = eink_grey_display(i);
                    PRINT_DEBUG("time:%d\n", millis());
                    if (grey_display_flag)
                    {
                        digitalToggle(LED0);
                    }
                    // digitalWrite(LED0, HIGH);
                }
                digitalWrite(LED0, HIGH);
            }
#endif

#elif EPD_COLOR == 3

            if (display_flag == 3)
            {

                digitalWrite(LED0, LOW);
                eink_TurnOnDisplay(EPD_DISPLAY_FULL);
                digitalWrite(LED0, HIGH);

            }

            else if (display_flag == 4)
            {

                digitalWrite(LED0, LOW);
                PRINT_DEBUG("time:%d\n", millis());


                eink_clear();

                digitalWrite(LED0, HIGH);
                eink_grey_data_inti();

                PRINT_DEBUG("time:%d\n", millis());

                for (int i = greyscale - 1; i > 0; i = i - 1)
                // for (int i =1; i<greyscale; i++)
                {

                    eink_setDepth(i);

                    if (greyscale == 8)
                        eink_inti(EPD_DISPLAY_Grey_Bwr8);
                    PRINT_DEBUG("time:%d\n", millis());
                    bool grey_display_flag = eink_grey_bwr_display(i);
                    PRINT_DEBUG("time:%d\n", millis());
                    if (grey_display_flag)
                    {
                        digitalToggle(LED0);
                    }
                    // digitalWrite(LED0, HIGH);
                }
                digitalWrite(LED0, HIGH);
            }

#endif
            display_flag = 0;
            HAL_Delay(100);
            HAL_Delay(1000);
            digitalWrite(LED0, LOW);
            NVIC_SystemReset(); //!!!!!!!!
            // SystemClock_MSI2_Config();
        }
        else
        {
            epd_adc_times += 1;
            if (epd_adc_times == 100)
            {
                display_flag = 0;
                PRINT_INFO("EPD VOL is too low,stopped.......\n");
                digitalWrite(LED0, HIGH);
                HAL_Delay(200);
                digitalWrite(LED0, LOW);
                HAL_Delay(200);
                digitalWrite(LED0, HIGH);
                HAL_Delay(200);
                digitalWrite(LED0, LOW);
            }
            HAL_Delay(40);
        }
    }
    if (nfc_data_flag == 1)
    {
        nfc_data_times++;
    }
    // if (0)
    if (nfc_data_times == 2 * 1000) // 1ms->1s
    {
        nfc_data_times = 0;
        nfc_data_flag = 0;
        bufferIndex = 0;
#ifdef VERSION2
        eink_image_length_reset();
#endif
        printf("NFC transfer data timeout!!!\n");
        digitalWrite(LED0, HIGH);
        HAL_Delay(200);
        digitalWrite(LED0, LOW);
        HAL_Delay(200);
        digitalWrite(LED0, HIGH);
        HAL_Delay(200);
        digitalWrite(LED0, LOW);
        HAL_Delay(200);
        digitalWrite(LED0, HIGH);
        HAL_Delay(200);
        digitalWrite(LED0, LOW);
    }
}

void BSP_GPO_Callback(void)
{
    /* Prevent unused argument(s) compilation warning */
    // GPOActivated = 1;
    GPOActivated += 1;
    // printf("GPO is activated\n");
    printf("GPO is activated:%d\n", millis());
    if (NFCIsBusy)
    {
        printf("NFC is busy:%d\n", millis());
        // GPOActivated = 0;
    }
    // TimerInterruptFlag++;
    // SystemClock_HSI16_Config();
    /* This function should be implemented by the user application.
       It is called into this driver when an event on Button is triggered. */
}

void Timer0Handler()
{
    TimerInterruptFlag = 1;
    Timer0.pause();
}

void ADC_Volt_Process(void)
{

    if (TimerInterruptFlag == 1)
    {
        TimerInterruptFlag = 0;
        uint32_t EPD_Vol = 2 * ADC_READ_Voltage(EPD_ADC);
        // PRINT_INFO("%dmv\n", EPD_Vol);
        PRINT_INFO("%dmv\n", EPD_Vol);
        if (EPD_Vol < EPD_VOL_TIMER)
        {
            digitalWrite(LED1, LOW);
        }
        else
        {
            digitalWrite(LED1, HIGH);
        }
        Timer0.resume();
    }
}
